home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / hdf / unix / hdf3_2r2.lha / HDF3.2r2 / util / he_cntrl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-28  |  35.4 KB  |  1,666 lines

  1. /***************************************************************************
  2. *
  3. *
  4. *                         NCSA HDF version 3.2r2
  5. *                            October 30, 1992
  6. *
  7. * NCSA HDF Version 3.2 source code and documentation are in the public
  8. * domain.  Specifically, we give to the public domain all rights for future
  9. * licensing of the source code, all resale rights, and all publishing rights.
  10. *
  11. * We ask, but do not require, that the following message be included in all
  12. * derived works:
  13. *
  14. * Portions developed at the National Center for Supercomputing Applications at
  15. * the University of Illinois at Urbana-Champaign, in collaboration with the
  16. * Information Technology Institute of Singapore.
  17. *
  18. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  19. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  20. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  21. *
  22. ****************************************************************************
  23. */
  24.  
  25. #ifdef RCSID
  26. static char RcsId[] = "@(#)$Revision: 1.7 $";
  27. #endif
  28. /*
  29. $Header: /hdf/hdf/v3.2r2/util/RCS/he_cntrl.c,v 1.7 1992/10/13 20:30:23 koziol beta koziol $
  30.  
  31. $Log: he_cntrl.c,v $
  32.  * Revision 1.7  1992/10/13  20:30:23  koziol
  33.  * Updates for v3.2r2 release
  34.  * .,
  35.  *
  36.  * Revision 1.1  1992/09/18  14:56:22  koziol
  37.  * Initial revision
  38.  *
  39.  * Revision 1.8  1992/09/11  18:32:51  chouck
  40.  * Assorted MAC mungings
  41.  *
  42.  * Revision 1.6  1992/08/24  21:59:44  sxu
  43.  * *** empty log message ***
  44.  *
  45.  * Revision 1.5  1992/08/18  19:49:46  chouck
  46.  * Added casts to string calls
  47.  *
  48.  * Revision 1.4  1992/07/31  21:10:24  chouck
  49.  * Use in-house print routines rather than fork() a call to od
  50.  *
  51.  * Revision 1.3  1992/07/15  21:48:48  sxu
  52.  * No change.
  53.  *
  54.  * Revision 1.2  1992/07/14  17:50:30  mlivin
  55.  * updated prompt with correct name
  56.  *
  57.  * Revision 1.1  1992/07/06  22:54:16  mlivin
  58.  * Initial revision
  59.  *
  60. */
  61. /* ------ he-cntrl.c ------  
  62.    This file contains much of the contol mechanisms for HDFed
  63.    - Many of the command line functions
  64.    - The parsing functions
  65.    - predicate handling
  66. */
  67.  
  68. #include "he.h"
  69.  
  70.  
  71. /* --- HEif --- executes commands if predicates are satisfied */
  72. #ifdef PROTOTYPE
  73. int HEif(HE_CMD *cmd)
  74. #else
  75. int HEif(cmd)
  76.     HE_CMD *cmd;
  77. #endif
  78. {
  79.     HE_PRED *pred;        /* predicates */
  80.     HE_CMD *cmdTail;        /* last cmd we've seen in the sublist */
  81.  
  82.     if (cmd->argc == 2 && !strcmp(cmd->argv[1],"-help"))
  83.     {
  84.     puts("if [<predicates>]");
  85.     puts("  <commands>*");
  86.     puts("end");
  87.     puts("\tExecutes commands if predicates are satisfied by element");
  88.     return HE_OK;
  89.     }
  90.  
  91.     /* parse the predicates on this command */
  92.     pred = parsePred(cmd->argc, cmd->argv);
  93.     if (!pred) return FAIL;
  94.  
  95.     /* execute the sub list only is the predicates are satisfied */
  96.     if (satPred(currDesc(), pred))
  97.     {
  98.     /* go through sub-list until an end is encountered */
  99.     for (cmdTail = cmd->sub; 
  100.              cmdTail && strcmp(cmdTail->argv[0], "end");
  101.          cmdTail = cmdTail->next)
  102.         if (cmdTail->func)
  103.         he_status = (*cmdTail->func) (cmdTail);
  104.         else
  105.         {
  106.         fprintf(stderr, "Unrecognized command: %s\n", cmd->argv[0]);
  107.         return FAIL;
  108.         }
  109.     }
  110.     return HE_OK;
  111. }
  112.  
  113. /* --- HEselect --- step through all the elements in a file and execute if
  114.    predicates are satisfied */
  115. #ifdef PROTOTYPE
  116. int HEselect(HE_CMD *cmd)
  117. #else
  118. int HEselect(cmd)
  119.     HE_CMD *cmd;
  120. #endif
  121. {
  122.     int t_currDesc;        /* tmp var */
  123.     HE_PRED *pred;        /* predicate structure */
  124.     HE_CMD *cmdTail;        /* last cmd we've seen in the sublist */
  125.  
  126.     if (cmd->argc == 2 && !strcmp(cmd->argv[1],"-help"))
  127.     {
  128.     puts("select [<predicates>]");
  129.     puts("  <commands>*");
  130.     puts("end");
  131.     puts("\tSteps through all elements in the file that satisfies the");
  132.     puts("\tpredicates and execute the commands on them.");
  133.     return HE_OK;
  134.     }
  135.  
  136.     /* generate predicate structure for this predicate list */
  137.     pred = parsePred(cmd->argc, cmd->argv);
  138.     if (!pred) return FAIL;
  139.  
  140.     /* save the curr desc index */
  141.     t_currDesc = he_currDesc;
  142.  
  143.     /* step through all elements */
  144.     for (he_currDesc = 0; he_currDesc < he_numDesc; he_currDesc++)
  145.     if (currTag() != DFTAG_NULL && satPred(currDesc(), pred))
  146.         for (cmdTail = cmd->sub; strcmp(cmdTail->argv[0], "end");
  147.          cmdTail = cmdTail->next)
  148.         if (cmdTail->func)
  149.             he_status = (*cmdTail->func) (cmdTail);
  150.         else
  151.         {
  152.             fprintf(stderr, "Unrecognized command: %s\n",
  153.                 cmdTail->argv[0]);
  154.             he_status = FAIL;
  155.         }
  156.  
  157.     /* restore he_currDesc */
  158.     he_currDesc = t_currDesc;
  159.  
  160.     return HE_OK;
  161. }
  162.  
  163. /* --- move to the next item --- */
  164.  
  165. extern HE_PRED *he_predicates;
  166.  
  167. #ifdef PROTOTYPE
  168. int HEnext(HE_CMD *cmd)
  169. #else
  170. int HEnext(cmd)
  171.     HE_CMD *cmd;
  172. #endif
  173. {
  174.     int tmp;
  175.     HE_PRED *predicates;
  176.     HE_PRED *parsePred();
  177.  
  178.     if (cmd->argc == 2 && !strcmp(cmd->argv[1],"-help"))
  179.     {
  180.     puts("next [<predicates>]");
  181.     puts("\tMove to the next element that satisfies the predicate");
  182.     return HE_OK;
  183.     }
  184.  
  185.     if (!fileOpen())
  186.     {
  187.     noFile();
  188.         return HE_FAIL;
  189.     }
  190.  
  191.     predicates = parsePred(cmd->argc, cmd->argv);
  192.  
  193.     /* the following code assumes that parsePred() returns NULL if error, */
  194.     /* a predicate struct with no key if empty predicate list */
  195.     if (!predicates) return HE_FAIL;
  196.  
  197.     /* replace this only if it is non-empty */
  198.     if (predicates[0].key != 0)
  199.     {
  200.     if (he_predicates) free(he_predicates);
  201.     he_predicates = predicates;
  202.     }
  203.  
  204.     tmp = he_currDesc;
  205.     do
  206.     {
  207.     if (tmp >= he_numDesc - 1)
  208.     {
  209.         fprintf(stderr, "Reached end of file. Not moved.\n");
  210.         return HE_FAIL;
  211.     }
  212.     tmp++;
  213.     } while (he_desc[tmp].tag == DFTAG_NULL ||
  214.          !satPred(he_desc + tmp, he_predicates));
  215.  
  216.     he_currDesc = tmp;
  217.  
  218.     return HE_OK;
  219. }
  220.  
  221. /* ---------- Move to previous item -------------- */
  222.  
  223. #ifdef PROTOTYPE
  224. int HEprev(HE_CMD *cmd)
  225. #else
  226. int HEprev(cmd)
  227.     HE_CMD *cmd;
  228. #endif
  229. {
  230.     int tmp;
  231.     HE_PRED *predicates;
  232.     HE_PRED *parsePred();
  233.  
  234.     if (cmd->argc == 2 && !strcmp(cmd->argv[1],"-help"))
  235.     {
  236.     puts("prev [<predicates>]");
  237.     puts("\tMove to the next element that satisfies the predicate");
  238.     return HE_OK;
  239.     }
  240.  
  241.     if (!fileOpen())
  242.     {
  243.         noFile();
  244.         return HE_FAIL;
  245.     }
  246.  
  247.     predicates = parsePred(cmd->argc, cmd->argv);
  248.  
  249.     /* the following code assumes that parsePred() returns NULL if error,
  250.        a predicate struct with no key if empty predicate list */
  251.     if (!predicates) return HE_FAIL;
  252.  
  253.     if (predicates[0].key != 0)
  254.     {
  255.     if (he_predicates) free(he_predicates);
  256.     he_predicates = predicates;
  257.     }
  258.  
  259.     tmp = he_currDesc;
  260.     do
  261.     {
  262.     if (tmp <= 0)
  263.     {
  264.         fprintf(stderr, "Reached beginning of file. Not moved.\n");
  265.         return HE_FAIL;
  266.     }
  267.     tmp--;
  268.     } while (he_desc[tmp].tag == DFTAG_NULL ||
  269.          !satPred(he_desc + tmp,he_predicates));
  270.     he_currDesc = tmp;
  271.  
  272.     return HE_OK;
  273. }
  274.  
  275. /* ----------- routines to call od on some objects ----------- */
  276.  
  277. #ifdef PROTOTYPE
  278. int HEdump(HE_CMD *cmd)
  279. #else
  280. int HEdump(cmd)
  281.     HE_CMD *cmd;
  282. #endif
  283. {
  284.     register int i;
  285.     int offset = 0, raw = 0;
  286.     char *format = "-o";
  287.     int32 length = 0;        /* zero is special, means all */
  288.  
  289.     for (i = 1; i < cmd->argc; i++)
  290.     if (cmd->argv[i][0] == '-')
  291.         switch (findOpt(cmd->argv[i] + 1))
  292.         {
  293.         case HE_HELP:
  294.         printf("dump [-offset <offset>] [-length <len>]\n"); 
  295.         printf("\t[-decimal|-octal|-hexidecimal|-float|-ascii]\n");
  296.         printf("\tDisplay the contents of the current element\n");
  297.         printf("\t-offset\t\tStart offset\n");
  298.         printf("\t-length\t\tLength to look at\n");
  299.         printf("\t-decimal\tDecimal format [32 bit integers]\n");
  300.         printf("\t-short\tDecimal format   [16 bit integers]\n");
  301.         printf("\t-byte\tDecimal format    [8 bit integers]\n");
  302.         printf("\t-octal\t\tOctal format [Default]\n");
  303.         printf("\t-hexidecimal\tHexidecimal format\n");
  304.         printf("\t-float\t\tFloat format   [32 bit floats]\n");
  305.         printf("\t-double\t\tFloat format  [64 bit floats]\n");
  306.         printf("\t-ascii\t\tAscii format\n");
  307.         return HE_OK;
  308.         case HE_OFFSET:
  309.         offset = atoi(cmd->argv[++i]);
  310.         break;
  311.         case HE_LENGTH:
  312.         length = atoi(cmd->argv[++i]);
  313.         if (length <= 0)
  314.         {
  315.             fprintf(stderr,"Illegal length: %s, ignored.\n",
  316.                 cmd->argv[i]);
  317.             length = 0;
  318.         }
  319.         break;
  320.         case HE_DECIMAL:
  321.         format = "-d";
  322.         break;
  323.         case HE_SHORT:
  324.         format = "-s";
  325.         break;
  326.         case HE_BYTE:
  327.         format = "-b";
  328.         break;
  329.         case HE_OCTAL:
  330.         format = "-o";
  331.         break;
  332.         case HE_HEX:
  333.         format = "-x";
  334.         break;
  335.         case HE_FLOAT:
  336.         format = "-f";
  337.         break;
  338.         case HE_DOUBLE:
  339.         format = "-e";
  340.         break;
  341.         case HE_ASCII:
  342.         format = "-a";
  343.         break;
  344.             case HE_RAW:
  345.                 raw = DFNT_NATIVE;
  346.                 break;
  347.         case HE_NOTFOUND:
  348.         unkOpt(cmd->argv[i]);
  349.         return HE_FAIL;
  350.         case HE_AMBIG:
  351.         ambigOpt(cmd->argv[i]);
  352.         return HE_FAIL;
  353.         default:
  354.         irrOpt(cmd->argv[i]);
  355.         return HE_FAIL;
  356.         }
  357.     else
  358.     {
  359.         unkArg(cmd->argv[i]);
  360.         return HE_FAIL;
  361.     }
  362.     return dump(length, offset, format, raw);
  363. }
  364.  
  365.  
  366. #define MAX_LINE 60
  367.  
  368. /*
  369.  * Run 'od' on a segment of the current data element
  370.  */
  371. #ifdef PROTOTYPE
  372. int dump(int32 length, int offset, char *format, int raw_flag)
  373. #else
  374. int dump(length, offset, format, raw_flag)
  375.     int32 length;            /* length of segment to look at */
  376.     int offset;            /* offset from start of data element */
  377.     char *format;        /* od arg, e.g. -x for hexidecimal */
  378.     int raw_flag;
  379. #endif
  380. {
  381.     int32 eltLength;
  382.     register int32 i;
  383.     register int len = 0;
  384.     char *data;
  385.  
  386.     if (!fileOpen()) {
  387.     noFile();
  388.     return HE_FAIL;
  389.     }
  390.  
  391.     eltLength = getElement(he_currDesc, &data);
  392.     if (eltLength <= 0) {
  393.     fprintf(stderr, "Unable to get element.\n");
  394.     return HE_FAIL;
  395.     }
  396.  
  397.     /* adjust the offset, negative offset implies starting from end. then
  398.        check to see if offset is in range */
  399.     if (offset < 0)
  400.     offset += eltLength;
  401.     if (offset < 0 || offset > eltLength) {
  402.     fprintf(stderr,"Illegal offset. Setting offset to 0.\n");
  403.     offset = 0;
  404.     }
  405.  
  406.     /* adjust the length if it falls beyond the end of the element */
  407.     if (length == 0 || length > (eltLength - offset))
  408.     length = eltLength - offset;
  409.  
  410.     /*
  411.      * Dump the data to the console
  412.      */
  413.  
  414.     switch(format[1]) {
  415.  
  416.     case 'd':
  417.         {
  418.             register int32 *idata;
  419.             idata = (int32 *) HDgetspace(length);
  420.  
  421.             DFKsetNT(DFNT_INT32 | raw_flag);
  422.             DFKnumout(data + offset, idata, length / 4, 0, 0);
  423.  
  424.             printf("%8d: ", offset); 
  425.             for(i = 0; i < length/4; i++) {
  426.                 printf("%11d ", idata[i]);
  427.                 if(++len > 4) {len = 0; printf("\n%8d: ", (offset + (i + 1) * 4));} 
  428.             }  
  429.             printf("\n");
  430.             HDfreespace(idata);
  431.         }
  432.         break;
  433.  
  434.     case 's':
  435.         {
  436.             register int16 *sdata;
  437.             sdata = (int16 *) HDgetspace(length);
  438.  
  439.             DFKsetNT(DFNT_INT16 | raw_flag);
  440.             DFKnumout(data + offset, sdata, length/2, 0, 0);
  441.  
  442.             printf("%8d: ", offset); 
  443.             for(i = 0; i < length/2; i++) {
  444.                 printf("%10d ", sdata[i]);
  445.                 if(++len > 5) {len = 0; printf("\n%8d: ", (offset + (i + 1) * 2));} 
  446.             } 
  447.             printf("\n");
  448.             HDfreespace(sdata);
  449.         }
  450.         break;
  451.  
  452.     case 'b':
  453.         {
  454.             register int8 *bdata;
  455.             bdata = (int8 *) HDgetspace(length);
  456.           
  457.             DFKsetNT(DFNT_INT8 | raw_flag);
  458.             DFKnumout(data + offset, bdata, length, 0, 0); 
  459.  
  460.             printf("%8d: ", offset); 
  461.             for(i = 0; i < length; i++) {
  462.                 printf("%6d ", bdata[i]);
  463.                 if(++len > 7) {len = 0; printf("\n%8d: ", (offset + (i + 1)));} 
  464.             }
  465.             printf("\n");
  466.             HDfreespace(bdata);
  467.         }
  468.         break;
  469.         
  470.     case 'x':
  471.         {
  472.             register int32 *idata;
  473.             idata = (int32 *) HDgetspace(length);
  474.  
  475.             DFKsetNT(DFNT_INT32 | raw_flag);
  476.             DFKnumout(data + offset, idata, length / 4, 0, 0); 
  477.  
  478.             printf("%8d: ", offset); 
  479.             for(i = 0; i < length / 4; i++) {
  480.                 printf("%10x ", idata[i]);
  481.                 if(++len > 5) {len = 0; printf("\n%8d: ", (offset + (i + 1) * 4));} 
  482.             }
  483.             printf("\n"); 
  484.             HDfreespace(idata);
  485.         }
  486.         break;
  487.  
  488.     case 'o':
  489.         {
  490.             register int32 *idata;
  491.             idata = (int32 *) HDgetspace(length);
  492.             
  493.             DFKsetNT(DFNT_INT32 | raw_flag);
  494.             DFKnumout(data + offset, idata, length / 4, 0, 0); 
  495.             
  496.             printf("%8d: ", offset);
  497.             for(i = 0; i < length / 4; i++) {
  498.                 printf("%10o ", idata[i]);
  499.                 if(++len > 4) {len = 0; printf("\n%8d: ", (offset + (i + 1) * 4));} 
  500.             }
  501.             printf("\n");
  502.             HDfreespace(idata);
  503.         }
  504.         break;
  505.  
  506.     case 'a':
  507.         {
  508.             register char *cdata;
  509.             cdata = (char *) (data + offset); 
  510.             printf("%8d: ", offset);
  511.             for(i = 0; i < length; i++) {
  512.                 printf("%5c ", cdata[i]);
  513.                 if(++len > 9) {len = 0; printf("\n%8d: ", (offset + (i + 1)));}    
  514.             }
  515.             printf("\n");
  516.         }
  517.         break;
  518.  
  519.     case 'f':
  520.         {
  521.             register float32 *fdata;
  522.             fdata = (float32 *) HDgetspace(length);
  523.   
  524.             DFKsetNT(DFNT_FLOAT32 | raw_flag);
  525.             DFKnumout(data + offset, fdata, length / 4, 0, 0); 
  526.  
  527.             printf("%8d: ", offset);
  528.             for(i = 0; i < length / 4; i++) {
  529.                 printf("%15e", fdata[i]);
  530.                 if(++len > 3) {len = 0; printf("\n%8d: ", (offset + (i + 1) * 4));}
  531.             }
  532.             printf("\n");
  533.             HDfreespace(fdata);
  534.         }
  535.         break;
  536.  
  537.     case 'e':
  538.         {
  539.             register float64 *fdata;
  540.             fdata = (float64 *) HDgetspace(length);
  541.   
  542.             DFKsetNT(DFNT_FLOAT32 | raw_flag);
  543.             DFKnumout(data + offset, fdata, length / 8, 0, 0); 
  544.  
  545.             printf("%8d:\t", offset);
  546.             for(i = 0; i < length / 8; i++) {
  547.                 printf("%30e", fdata[i]);
  548.                 if(++len > 1) {len = 0; printf("\n%8d: ", (offset + (i + 1) * 8));}
  549.             }
  550.             printf("\n"); 
  551.             HDfreespace(fdata);
  552.         }
  553.         break;
  554.  
  555.     default:
  556.         printf("Doing the default thang\n");
  557.         break;
  558.  
  559.     }
  560.  
  561.     free(data);
  562.  
  563.     return HE_OK;
  564. }
  565.  
  566. /* ------------------ Print 'info' ----------------- */
  567.  
  568. #ifdef PROTOTYPE
  569. int HEinfo(HE_CMD *cmd)
  570. #else
  571. int HEinfo(cmd)
  572.     HE_CMD *cmd;
  573. #endif
  574. {
  575.   register int i;
  576.   int all = NO;
  577.   int longout = NO;
  578.   int group = NO;
  579.   int label = NO;
  580.   
  581.   for (i = 1; i < cmd->argc; i++)
  582.     if (cmd->argv[i][0] == '-')
  583.       switch (findOpt(cmd->argv[i] + 1))
  584.         {
  585.         case HE_HELP:
  586.           puts("info [-all] [-long] [-group] [-label]");
  587.           puts("\t-all\t\tShow info for all elements in file");
  588.           puts("\t-long\t\tShow more info");
  589.           puts("\t-group\t\tOrganize info in group(s)");
  590.           puts("\t-label\t\tShow label if any");
  591.           return HE_OK;
  592.         case HE_LONGOUT:
  593.           longout = YES;
  594.           break;
  595.         case HE_ALL:
  596.           all = YES;
  597.           break;
  598.         case HE_LABEL:
  599.           label = YES;
  600.           break;
  601.         case HE_DOGROUP:
  602.           group = YES;
  603.           break;
  604.         case HE_NOTFOUND:
  605.           unkOpt(cmd->argv[i]);
  606.           return HE_FAIL;
  607.         case HE_AMBIG:
  608.           ambigOpt(cmd->argv[i]);
  609.           return HE_FAIL;
  610.         default:
  611.           irrOpt(cmd->argv[i]);
  612.           return HE_FAIL;
  613.         }
  614.     else
  615.       {
  616.         unkArg(cmd->argv[i]);
  617.         return HE_FAIL;
  618.       }
  619.   return info(all, longout, group, label);
  620. }
  621.  
  622. /*
  623.  *Show info about data elements
  624.  */
  625. #ifdef PROTOTYPE
  626. int info(int all, int longout, int group, int label)
  627. #else
  628. int info(all, longout, group, label)
  629.     int all;            /* select all elements */
  630.     int longout;        /* long output */
  631.     int group;            /* arrange output in groups */
  632.     int label;            /* show labels */
  633. #endif
  634. {
  635.     int idx;
  636.     int empty = 0;
  637.     int start, end;
  638.     int d;
  639.     int *mark;
  640.     register int i, j;
  641.  
  642.     if (!fileOpen()) {
  643.       noFile();
  644.       return HE_OK;
  645.     }
  646.  
  647.     if (!group || (!isGrp(currTag()) && !all)) {
  648.       if (all) {
  649.         start = 0;
  650.         end = he_numDesc - 1;
  651.       }
  652.       else
  653.         start = end = he_currDesc;
  654.       
  655.       for (i = start; i <= end; i++)
  656.         if (he_desc[i].tag == DFTAG_NULL)
  657.           empty++;
  658.         else
  659.           {
  660.             if (all && i == he_currDesc)
  661.               printf("*");
  662.             else
  663.               printf(" ");
  664.             printf("(%d) ", i+1); /* 1 based */
  665.             infoDesc(i, longout, label);
  666.           }
  667.       
  668.     if (empty > 0)
  669.         printf("Empty (tag %d) : %d slots.\n", DFTAG_NULL, empty);
  670.     }
  671.     else
  672.     {
  673.     mark = (int *) calloc(he_numDesc, sizeof(int));
  674.  
  675.     if (all)
  676.     {
  677.         start = 0;
  678.         end = he_numGrp - 1;
  679.     }
  680.     else
  681.     {
  682.         if (he_numGrp == 0)
  683.         {
  684.         fprintf(stderr, "There is no group in this file.\n");
  685.         return HE_FAIL;
  686.         }
  687.         start = end = currGrpNo();
  688.     }
  689.     for (i = start; i <= end; i++)
  690.     {
  691.         printf("**Group %d:\n", i+1); /* 1 based */
  692.         idx = he_grp[i].desc;
  693.         infoDesc(idx, longout, label);
  694.  
  695.         mark[idx] = YES;
  696.  
  697.         for (j = 0; j < he_grp[i].size; j ++)
  698.         if ((d = findDesc(he_grp[i].ddList + j)) >= 0)
  699.         {
  700.             mark[d] = 1;
  701.             infoDesc(d, longout, 0);
  702.         }
  703.         else
  704.             fprintf(stderr,
  705.                 "**Tag: %d, Ref: %d not in descriptors list!\n",
  706.                 he_grp[i].ddList[j].tag,
  707.                 he_grp[i].ddList[j].ref);
  708.     }
  709.     if (all)
  710.     {
  711.         puts("\n**These do not belong to any group:");
  712.         for (i = 0; i < he_numDesc; i++)
  713.         if (!mark[i])
  714.             if (he_desc[i].tag == DFTAG_NULL)
  715.             empty++;
  716.             else
  717.             infoDesc(i, longout, label);
  718.  
  719.         if (empty > 0)
  720.         printf("Empty (tag %d) : %d slots.\n", DFTAG_NULL, empty);
  721.     }
  722.     }
  723.     return HE_OK;
  724. }
  725.  
  726. #ifdef PROTOTYPE
  727. void infoDesc(int desc, int longout, int label)
  728. #else
  729. void infoDesc(desc, longout, label)
  730.     int desc;
  731.     int longout;
  732.     int label;
  733. #endif
  734. {
  735.     char *s, *name;
  736.  
  737.     name = HDgettagname(he_desc[desc].tag);
  738.     if(!name) name = "Unknown Tag";
  739.  
  740.     printf("\t%-30s: (Tag %d)", name, he_desc[desc].tag);
  741.  
  742.     if (longout)
  743.     printf("\n\tRef: %d, Offset: %d, Length: %d (bytes)\n",
  744.            he_desc[desc].ref, he_desc[desc].offset, he_desc[desc].length);
  745.     else
  746.     printf(" Ref %d\n", he_desc[desc].ref);
  747.     if (label)
  748.     {
  749.     getAnn(HE_LABEL, he_desc[desc].tag, he_desc[desc].ref, &s);
  750.     if (s != NULL) printf("\tLabel: %s\n",s);
  751.     }
  752. }
  753.  
  754. /* ---------- HEdelete --- 'stub' function for delete */
  755. #ifdef PROTOTYPE
  756. int HEdelete(HE_CMD *cmd)
  757. #else
  758. int HEdelete(cmd)
  759.     HE_CMD *cmd;
  760. #endif
  761. {
  762.     if (cmd->argc < 2)
  763.     return delete(he_currDesc);
  764.     else
  765.     {
  766.     if (cmd->argv[1][0] != '-') {
  767.         unkArg(cmd->argv[1]);
  768.             return HE_FAIL;
  769.         }
  770.     else
  771.         switch (findOpt(cmd->argv[1] + 1))
  772.         {
  773.         case HE_HELP:
  774.         puts("delete");
  775.         puts("\tDelete this element or group.");
  776.         return HE_OK;
  777.         case HE_NOTFOUND:
  778.         unkOpt(cmd->argv[1]);
  779.         return HE_FAIL;
  780.         case HE_AMBIG:
  781.         ambigOpt(cmd->argv[1]);
  782.         return HE_FAIL;
  783.         default:
  784.         irrOpt(cmd->argv[1]);
  785.         return HE_FAIL;
  786.         }
  787.     }
  788. }
  789.  
  790. /* delete -- deletes a group and its elts or an elt from current hdf file */
  791. #ifdef PROTOTYPE
  792. int delete(int curr)
  793. #else
  794. int delete(curr)
  795.     int curr;
  796. #endif
  797. {
  798.     int ret;
  799.  
  800.     /* check if any file is open */
  801.     if (!fileOpen())
  802.     {
  803.     noFile();
  804.     return HE_FAIL;
  805.     }
  806.  
  807.     /* call the actual routine to do it, the update the descriptor list */
  808.     ret = recurseDel(curr);
  809.     updateDesc();
  810.  
  811.     return ret;
  812. }
  813.  
  814. /* recurseDel -- this function recursively tries to delete some elts from
  815.    a file. if the current elt is a group, it will call itself on the elts
  816.    of the group. else, it will check if any group references the elt, and
  817.    actually deletes it if there is no other references */
  818. #ifdef PROTOTYPE
  819. int recurseDel(int curr)
  820. #else
  821. int recurseDel(curr)
  822.     int curr;
  823. #endif
  824. {
  825.     int d, currGrp;
  826.     register int i;
  827.  
  828.     if (isGrp(he_desc[curr].tag))
  829.     {
  830.     /* if this is a group, do its elts then itself */
  831.  
  832.     /* find the index of the group */
  833.     currGrp = desc2Grp(curr);
  834.  
  835.     /* step through the elts of this group */
  836.     for ( i = 0; i < he_grp[currGrp].size ; i++)
  837.     {
  838.         d =  findDesc(he_grp[currGrp].ddList + i);
  839.         if (d >= 0)
  840.         {
  841.         /* null this so it will not report that this is a multiple
  842.          * copy of itself */
  843.         he_grp[currGrp].ddList[i].tag = DFTAG_NULL;
  844.         he_grp[currGrp].ddList[i].ref = 0;
  845.  
  846.         /* Try to delete this component */
  847.         if (recurseDel(d) < 0) return HE_FAIL;
  848.         }
  849.     }
  850.     /* tried all components, now delete self */
  851.     if (!hasReference(curr))
  852.         if (deleteDesc(curr) < 0)
  853.         return HE_FAIL;
  854.     }
  855.     else
  856.     /* not a group, actually delete this only if there is no group
  857.        referencing it */
  858.     if (!hasReference(curr))
  859.         if (deleteDesc(curr) < 0)
  860.         return HE_FAIL;
  861.     return HE_OK;
  862. }
  863.  
  864. /* some char const for the get/parse routines */
  865. #define CR '\n'
  866. #define SPACE ' '
  867. #define TAB '\t'
  868. #define QUOTE '"'
  869. #define BREAK '\003'        /* C-c */
  870. #define ESCAPE '\\'        /* Quote escape */
  871. #define COMMENT '!'        /* Comment a line if first character */
  872.  
  873. /* max line size -- change this if you type longer than this in one line */
  874. #define HE_LINE_SZ 512
  875.  
  876. /* command separator */
  877. #define HE_SEPARATOR ';'
  878.  
  879. /* is this in batch mode or interactive? */
  880. int he_batch = NO;
  881.  
  882. /* nesting when if/select is encountered */
  883. int he_nestLevel = 0;
  884.  
  885. /* prompt is actually "he"<he_prompt><space> */
  886. char *he_prompt = ">";
  887. char he_nestChar = '>';
  888.  
  889. /* table to associate command to the function --
  890.    add additional functions anywhere in the table BEFORE the
  891.    Marker {0,0} entry */
  892. struct {
  893.     char *str;
  894.     HE_FUNC func;
  895. } he_funcTab[] =
  896. {
  897. {"open",     (HE_FUNC) HEopen},
  898. {"close",    (HE_FUNC) HEclose},
  899. {"next",     (HE_FUNC) HEnext},
  900. {"prev",     (HE_FUNC) HEprev},
  901. {"alias",    (HE_FUNC) HEalias},
  902. {"unalias",  (HE_FUNC) HEunalias},
  903. {"display",  (HE_FUNC) HEdisplay},
  904. {"info",     (HE_FUNC) HEinfo},
  905. {"list",     (HE_FUNC) HEinfo},
  906. {"if",       (HE_FUNC) HEif},
  907. {"select",   (HE_FUNC) HEselect},
  908. {"wait",     (HE_FUNC) HEwait},
  909. {"delete",   (HE_FUNC) HEdelete},
  910. {"quit",     (HE_FUNC) HEquit},
  911. {"dump",     (HE_FUNC) HEdump},
  912. {"getr8",    (HE_FUNC) HEgetR8},
  913. {"putr8",    (HE_FUNC) HEputR8},
  914. {"put",      (HE_FUNC) HEput},
  915. {"revert",   (HE_FUNC) HErevert},
  916. {"write",    (HE_FUNC) HEwrite},
  917. {"annotate", (HE_FUNC) HEannotate},
  918. {"help",     (HE_FUNC) HEhelp},
  919. {"end",      (HE_FUNC) 0},
  920. {NULL,       (HE_FUNC) 0},            /* Marker */
  921. };
  922.  
  923. #ifdef PROTOTYPE
  924. HE_FUNC findFunc(char *word)
  925. #else
  926. HE_FUNC findFunc(word)
  927.     char *word;
  928. #endif /* PROTOTYPE */
  929. {
  930.     int len;
  931.     int found = -1;
  932.     register int i;
  933.  
  934.     len = strlen((const char *) word);
  935.  
  936.     for (i = 0; he_funcTab[i].str; i++)
  937.     if (!strncmp(he_funcTab[i].str, (const char *) word, len))
  938.     {
  939.         /* check for exact match */
  940.         if (strlen(he_funcTab[i].str) == len)
  941.         return he_funcTab[i].func;
  942.  
  943.         if (found < 0)
  944.         found = i;
  945.         else
  946.         {
  947.         fprintf(stderr,"Ambiguous command: %s.\n", word);
  948.         return NULL;
  949.         }
  950.     }
  951.  
  952.     if (found < 0) 
  953.       return NULL;
  954.     else
  955.       return he_funcTab[found].func;
  956. }
  957.  
  958. /* prompt -- printout prompt according to the nesting level */
  959. #ifdef PROTOTYPE
  960. void prompt(void)
  961. #else
  962. void prompt()
  963. #endif
  964. {
  965.  
  966. #ifndef MAC
  967.  
  968.     if (!he_nestLevel)
  969.     printf("hdfed%s ", he_prompt);
  970.     else
  971.     {
  972.     register int i;
  973.  
  974.     printf("     %s ", he_prompt);
  975.     for (i = he_nestLevel; i; i--) putchar(he_nestChar);
  976.     putchar(' ');
  977.     }
  978.  
  979. #endif /* MAC */
  980.  
  981. }
  982.  
  983.  
  984. /* reads a line of input into p */
  985. /* Skips all initial spaces and empty commands */
  986. /* always returns with at least a word in p, unless eof */
  987. /* if eof and p is not empty, return HE_OK, else if no word, return EOF */
  988. #ifdef PROTOTYPE
  989. int getLine(register char *p)
  990. #else
  991. int getLine(p)
  992.     register char *p;
  993. #endif
  994. {
  995.     static int ch = 0;
  996.  
  997.     do
  998.     {
  999.     if (!he_batch && (ch != EOF)) prompt();
  1000.     ch = getc(stdin);
  1001.     if (ch == COMMENT)
  1002.     {
  1003.         /* Skip this line */
  1004.         do ch = getchar();
  1005.         while ((ch != CR) && (ch != EOF));
  1006.     }
  1007.     else
  1008.         while ((ch == SPACE) || (ch == TAB) || (ch == HE_SEPARATOR))
  1009.         ch = getchar();
  1010.     if (ch == EOF) return EOF;
  1011.     } while (ch == CR);
  1012.  
  1013.     while ((ch != EOF) && (ch != CR))
  1014.     switch(ch)
  1015.     {
  1016.     case ESCAPE:
  1017.         ch = getchar();
  1018.         if (!(ch == CR)) *p++ = ch;
  1019.         ch = getchar();
  1020.         break;
  1021.     case QUOTE:
  1022.         ch = getchar();
  1023.         while (ch != QUOTE)
  1024.         {
  1025.         if (ch == ESCAPE) ch = getchar();
  1026.         *p++ = ch;
  1027.         ch = getchar();
  1028.         }
  1029.         ch = getchar();    /* Skip over the QUOTE */
  1030.         break;
  1031.     case SPACE:
  1032.     case TAB:
  1033.         *p++ = SPACE;
  1034.         while ((ch == SPACE) || (ch == TAB)) ch = getchar();
  1035.         break;
  1036.     case HE_SEPARATOR:
  1037.         if (!isspace(*(p-1))) *p++ = SPACE;
  1038.         *p++ = HE_SEPARATOR;
  1039.         ch = SPACE;        /* Ensure next is a space */
  1040.         break;
  1041.     default:
  1042.         *p++ = ch;
  1043.         ch = getchar();
  1044.         break;
  1045.     }
  1046.  
  1047.     *p++ = '\0';
  1048.     return ch;
  1049. }
  1050.  
  1051. /* copy the next (space-delimited) word and advance the pointer as a
  1052.    side effect */
  1053. #ifdef PROTOTYPE
  1054. char *nextWord(char **p)
  1055. #else
  1056. char *nextWord(p)
  1057.     char **p;
  1058. #endif
  1059. {
  1060.     char *word;
  1061.     register char *s, *q;
  1062.     int len;
  1063.  
  1064.     q = *p;
  1065.     while (*q && isspace(*q)) q++;
  1066.     if (!(*q))
  1067.     {
  1068.     *p = q;
  1069.     return NULL;
  1070.     }
  1071.  
  1072.     s = q;
  1073.     while (*s && !isspace(*s)) s++;
  1074.     len = s - q;
  1075.  
  1076.     word = (char *) malloc(len + 1);
  1077.     strncpy(word, q, len);
  1078.     word[len] = '\0';
  1079.  
  1080.     *p = s;
  1081.     while (**p && (isspace(**p))) (*p)++;
  1082.  
  1083.     return word;
  1084. }
  1085.  
  1086. #ifdef PROTOTYPE
  1087. HE_CMD *parseCmd(char **p)
  1088. #else
  1089. HE_CMD *parseCmd(p)
  1090.     char **p;
  1091. #endif
  1092. {
  1093.     char *word;
  1094.     HE_CMD *cmd;
  1095.     HE_CMD *aliasCmd;
  1096.     HE_CMD *cmdTail;
  1097.  
  1098.     if (!(**p)) return NULL;
  1099.  
  1100.     cmd = (HE_CMD *) calloc(1, sizeof(HE_CMD));
  1101.     cmd->next = cmd->sub = (HE_CMD *) NULL;
  1102.     cmd->argc = 1;
  1103.     cmd->argv[0] = nextWord(p);
  1104.  
  1105.     if (aliasCmd = findAlias(cmd->argv[0]))
  1106.     cmd = aliasCmd;
  1107.     else
  1108.     cmd->func = findFunc(cmd->argv[0]);
  1109.  
  1110.     if (((HE_CMD*) cmd->func == (HE_CMD*) HEalias) || 
  1111.         ((HE_CMD*) cmd->func == (HE_CMD*) HEwait)) {
  1112.       /* let the alias command handle the parsing */
  1113.       cmd->argv[1] = copyStr(*p);
  1114.       cmd->argc = 2;
  1115.       
  1116.       **p = '\0';
  1117.     }
  1118.     else
  1119.     {
  1120.     cmdTail = cmd;
  1121.     while (cmdTail->next) cmdTail = cmdTail->next;
  1122.  
  1123.     for (word = nextWord(p); word && strcmp(word, ";");
  1124.          word = nextWord(p), cmdTail->argc++)
  1125.         cmdTail->argv[cmdTail->argc] = word;
  1126.  
  1127.     while (**p && (isspace(**p) || (**p == ';'))) (*p)++;
  1128.     }
  1129.     return cmd;
  1130. }
  1131.  
  1132. /* Inputs a line and returns cmd list of line */
  1133. #ifdef PROTOTYPE
  1134. HE_CMD *parse(void)
  1135. #else
  1136. HE_CMD *parse()
  1137. #endif
  1138. {
  1139.     static char line[HE_LINE_SZ];
  1140.     static char *ptr;
  1141.     int notDone = 1;
  1142.     HE_CMD *cmd;
  1143.     HE_CMD *cmdTail;
  1144.  
  1145.     if (getLine(line) == EOF) return NULL;
  1146.     ptr = line;
  1147.  
  1148.     cmdTail = cmd = parseCmd(&ptr);
  1149.     while (cmdTail->next) cmdTail = cmdTail->next;
  1150.  
  1151.     while (notDone)
  1152.     {
  1153.     cmdTail->next = parseCmd(&ptr);
  1154.     notDone = (cmdTail->next != NULL);
  1155.     while (cmdTail->next) cmdTail = cmdTail->next;
  1156.     }
  1157.     return cmd;
  1158. }
  1159.  
  1160. #ifdef PROTOTYPE
  1161. HE_CMD *getCmd(void)
  1162. #else
  1163. HE_CMD *getCmd()
  1164. #endif
  1165. {
  1166.     static HE_CMD *cmdList;
  1167.     HE_CMD *cmd;
  1168.     HE_CMD *cmdTail;
  1169.  
  1170.     if(!cmdList) 
  1171.       cmdList = parse();
  1172.     if(!cmdList) 
  1173.       return NULL;
  1174.  
  1175.     cmd = cmdList;
  1176.     if (cmdList) cmdList = cmdList->next;
  1177.     cmd->next = (HE_CMD *) NULL; /* Cut off links since these will be */
  1178.                  /* accessed later */
  1179.  
  1180.     if (cmd && (((HE_CMD*)cmd->func == (HE_CMD*)HEif) ||
  1181.                 ((HE_CMD*)cmd->func == (HE_CMD*)HEselect)) &&
  1182.     !((cmd->argc > 1) && (cmd->argv[1][0] == '-') &&
  1183.       (findOpt(cmd->argv[1]+1) == HE_HELP)))
  1184.     {
  1185.     he_nestLevel++;
  1186.  
  1187.     cmd->sub = getCmd();
  1188.     for (cmdTail = cmd->sub;
  1189.          cmdTail && strcmp(cmdTail->argv[0], "end"); /* while != "end" */
  1190.          cmdTail = cmdTail->next)
  1191.         cmdTail->next = getCmd();
  1192.  
  1193.     he_nestLevel--;
  1194.     }
  1195.     return cmd;
  1196. }
  1197.  
  1198. #define HE_ALIAS_SZ 256
  1199.  
  1200. struct he_alias {
  1201.     char *str;
  1202.     HE_CMD *cmd;
  1203. } he_aliasTab[HE_ALIAS_SZ];
  1204.  
  1205. int he_numAlias = 0;
  1206.  
  1207. #ifdef PROTOTYPE
  1208. int setAlias(char *str, HE_CMD *cmd)
  1209. #else
  1210. int setAlias(str, cmd)
  1211.     char *str;
  1212.     HE_CMD *cmd;
  1213. #endif
  1214. {
  1215.     register int i;
  1216.  
  1217.     for (i = 0; i < he_numAlias; i++)
  1218.     if (!strcmp(str, he_aliasTab[i].str))
  1219.     {
  1220.         he_aliasTab[i].cmd = cmd;
  1221.         return HE_OK;
  1222.     }
  1223.     if (he_numAlias == HE_ALIAS_SZ)
  1224.     {
  1225.     fprintf(stderr, "Alias table full.\n");
  1226.     return HE_FAIL;
  1227.     }
  1228.     he_aliasTab[he_numAlias].str = str;
  1229.     he_aliasTab[he_numAlias++].cmd = cmd;
  1230.  
  1231.     return HE_OK;
  1232. }
  1233.  
  1234. #ifdef PROTOTYPE
  1235. HE_CMD *mkDupCmd(HE_CMD *cmd)
  1236. #else
  1237. HE_CMD *mkDupCmd(cmd)
  1238.     HE_CMD *cmd;
  1239. #endif
  1240. {
  1241.     register int i;
  1242.     HE_CMD *dupCmd;
  1243.  
  1244.     dupCmd = (HE_CMD *) calloc(1, sizeof(HE_CMD));
  1245.     dupCmd->func = cmd->func;
  1246.     dupCmd->argc = cmd->argc;
  1247.     dupCmd->next = dupCmd->sub = (HE_CMD *) NULL;
  1248.     for (i = 0; i < cmd->argc; i++)
  1249.     dupCmd->argv[i] = copyStr(cmd->argv[i]);
  1250.  
  1251.     return dupCmd;
  1252. }
  1253.  
  1254. #ifdef PROTOTYPE
  1255. HE_CMD *findAlias(char *str)
  1256. #else
  1257. HE_CMD *findAlias(str)
  1258.     char *str;
  1259. #endif
  1260. {
  1261.     register int i;
  1262.     HE_CMD *cmd;
  1263.     HE_CMD *dupCmd;
  1264.     HE_CMD *cmdTail;
  1265.  
  1266.     for (i = 0; i < he_numAlias; i++)
  1267.     if (!strcmp(str, he_aliasTab[i].str))
  1268.     {
  1269.         cmd = he_aliasTab[i].cmd;
  1270.         dupCmd = mkDupCmd(cmd);
  1271.  
  1272.         cmd = cmd->next;
  1273.         for (cmdTail = dupCmd; cmd;
  1274.          cmd = cmd->next, cmdTail = cmdTail->next)
  1275.         cmdTail->next = mkDupCmd(cmd);
  1276.  
  1277.         return dupCmd;
  1278.     }
  1279.     return NULL;
  1280. }
  1281.  
  1282. #ifdef PROTOTYPE
  1283. int HEunalias(HE_CMD *cmd)
  1284. #else
  1285. int HEunalias(cmd)
  1286.     HE_CMD *cmd;
  1287. #endif
  1288. {
  1289.     register int a, i, j;
  1290.  
  1291.     for (a = 1; a < cmd->argc; a++)
  1292.     for (i = 0; i < he_numAlias; i++)
  1293.         if (!strcmp(cmd->argv[a], he_aliasTab[i].str))
  1294.         {
  1295.         he_numAlias--;
  1296.         for (j = i; j < he_numAlias; j++)
  1297.         {
  1298.             he_aliasTab[j].str = he_aliasTab[j+1].str;
  1299.             he_aliasTab[j].cmd = he_aliasTab[j+1].cmd;
  1300.         }
  1301.         break;
  1302.         }
  1303.     return HE_OK;
  1304. }
  1305.  
  1306. #ifdef PROTOTYPE
  1307. void printAlias(char *word, HE_CMD *cmd)
  1308. #else
  1309. void printAlias(word, cmd)
  1310.     char *word;
  1311.     HE_CMD *cmd;
  1312. #endif
  1313. {
  1314.     register int j;
  1315.  
  1316.     printf("%s:", word);
  1317.     for (; cmd; cmd = cmd->next)
  1318.     {
  1319.     printf("\t");
  1320.     for (j = 0; j < cmd->argc; j++) printf("%s ",cmd->argv[j]);
  1321.     puts("");
  1322.     }
  1323. }
  1324.  
  1325. #ifdef PROTOTYPE
  1326. int HEalias(HE_CMD *cmd)
  1327. #else
  1328. int HEalias(cmd)
  1329.     HE_CMD *cmd;
  1330. #endif
  1331. {
  1332.     char *s;
  1333.     char *word;
  1334.     register int i;
  1335.     HE_CMD *cmdTail;
  1336.  
  1337.     s = cmd->argv[1];
  1338.     word = nextWord(&s);
  1339.  
  1340.     if (!word)
  1341.     {
  1342.     for (i = 0; i < he_numAlias; i++)
  1343.         printAlias(he_aliasTab[i].str, he_aliasTab[i].cmd);
  1344.     return HE_OK;
  1345.     }
  1346.  
  1347.     cmd = parseCmd(&s);
  1348.     if (!cmd)
  1349.     {
  1350.     cmd = findAlias(word);
  1351.     printAlias(word, cmd);
  1352.     return HE_OK;
  1353.     }
  1354.     for (cmdTail = cmd; cmdTail->next;  cmdTail = cmdTail->next);
  1355.     while (cmdTail->next = parseCmd(&s))
  1356.     for (; cmdTail->next;  cmdTail = cmdTail->next);
  1357.     return setAlias(word, cmd);
  1358. }
  1359.  
  1360. HE_PRED *he_predicates;
  1361.  
  1362. /* resetPred -- for setting the he_predicates to point to a pred
  1363.    of only group, this is the default when a file is opened */
  1364. #ifdef PROTOTYPE
  1365. int resetPred(void)
  1366. #else
  1367. int resetPred()
  1368. #endif
  1369. {
  1370.     if (he_predicates != NULL)
  1371.     free(he_predicates);
  1372.  
  1373.     he_predicates = (HE_PRED *) calloc(2, sizeof(HE_PRED));
  1374.     he_predicates[0].key = HEK_GROUP;
  1375.     he_predicates[1].key = 0;
  1376.  
  1377.     return HE_OK;
  1378. }
  1379.  
  1380. struct {
  1381.     char *str;
  1382.     int key;
  1383. } he_keyTab[] =
  1384. {
  1385. {"!=",        HEK_NEQUAL | HE_COMPARATOR},
  1386. {"<",        HEK_LESST | HE_COMPARATOR},
  1387. {"<=",        HEK_LEQUAL | HE_COMPARATOR},
  1388. {"==",        HEK_EQUAL | HE_COMPARATOR},
  1389. {">",        HEK_GRT | HE_COMPARATOR},
  1390. {">=",        HEK_GEQUAL | HE_COMPARATOR},
  1391. {"all",        HEK_ALL | HE_PREDICATE},
  1392. {"any",        HEK_ALL | HE_PREDICATE},
  1393. {"ref",        HEK_REF | HE_PREDICATE},
  1394. {"succeed",    HEK_SUCCEED | HE_PREDICATE},
  1395. {"fail",    HEK_FAIL | HE_PREDICATE},
  1396. {"tag",        HEK_TAG | HE_PREDICATE},
  1397. {"group",    HEK_GROUP | HE_PREDICATE},
  1398. /* Finish this later */
  1399. {NULL, 0},            /* Marker */
  1400. };
  1401.  
  1402. #ifdef PROTOTYPE
  1403. int findKey(char *word)
  1404. #else
  1405. int findKey(word)
  1406.     char *word;
  1407. #endif
  1408. {
  1409.     register int i;
  1410.     int len;
  1411.     int found = -1;
  1412.  
  1413.     len = strlen(word);
  1414.  
  1415.     for (i = 0; he_keyTab[i].str; i++)
  1416.     if (!strncmp(he_keyTab[i].str, word, len))
  1417.     {
  1418.         /* if this is an exact match, just return */
  1419.         if (strlen(he_keyTab[i].str) == len)
  1420.         return he_keyTab[i].key;
  1421.         if (found < 0)
  1422.         found = i;
  1423.         else
  1424.         {
  1425.         fprintf(stderr, "Ambiguous: %s.\n", word);
  1426.         return HE_NOTFOUND;
  1427.         }
  1428.     }
  1429.     if (found < 0)
  1430.     {
  1431.     fprintf(stderr, "Predicate/comparator: %s not found.\n", word);
  1432.     return HE_NOTFOUND;
  1433.     }
  1434.     return he_keyTab[found].key;
  1435. }
  1436.  
  1437. #ifdef PROTOTYPE
  1438. int isNumber(register char *s)
  1439. #else
  1440. int isNumber(s)
  1441.     register char *s;
  1442. #endif
  1443. {
  1444.     for (; *s; s++)
  1445.     if (!isdigit((int) *s)) return NO;
  1446.  
  1447.     return YES;
  1448. }
  1449.  
  1450. #define HE_PRED_SZ HE_ARG_SZ
  1451.  
  1452. #ifdef PROTOTYPE
  1453. HE_PRED *parsePred(int argc, char *argv[])
  1454. #else
  1455. HE_PRED *parsePred(argc, argv)
  1456.     int argc;
  1457.     char *argv[];
  1458. #endif
  1459. {
  1460.     HE_PRED *pred;
  1461.     int predNum = -1;
  1462.     int state = 0;
  1463.     int key;
  1464.     register int i;
  1465.     char *s;
  1466.     char *tok;
  1467.  
  1468.     pred = (HE_PRED *) calloc(HE_PRED_SZ, sizeof(HE_PRED));
  1469.  
  1470.     for ( i = 1; i < argc; i++)
  1471.     {
  1472.     s = argv[i];
  1473.     while (*s)
  1474.     {
  1475.         if (state != 2) 
  1476.         tok = nextToken(&s);
  1477.         else
  1478.         tok = nextWord(&s);
  1479.         if (!tok) break;
  1480.  
  1481.         if (state != 2)
  1482.         {
  1483.         if ((key = findKey(tok)) == HE_NOTFOUND)
  1484.         {
  1485.             free(pred);
  1486.             return NULL;
  1487.         }
  1488.         free(tok);
  1489.         }
  1490.  
  1491.         switch(state)
  1492.         {
  1493.         case 0:
  1494.         /* Ready to accept a predicate */
  1495.         if (!(key & HE_PREDICATE))
  1496.         {
  1497.             fprintf(stderr, "Parse error: %s.\n", argv[i]);
  1498.             free(pred);
  1499.             return NULL;
  1500.         }
  1501.         pred[++predNum].key = key & ~(HE_PREDICATE | HE_COMPARATOR);
  1502.         state = 1;
  1503.         break;
  1504.  
  1505.         case 1:
  1506.         /* Can be a comparator for previous pred or a new predicate */
  1507.         if (key & HE_PREDICATE)
  1508.         {
  1509.             pred[++predNum].key =
  1510.             key & ~(HE_PREDICATE | HE_COMPARATOR);
  1511.  
  1512.         }
  1513.         else if (key & HE_COMPARATOR)
  1514.         {
  1515.             pred[predNum].Comp =
  1516.             key & ~(HE_PREDICATE | HE_COMPARATOR);
  1517.             state = 2;
  1518.         }
  1519.         else
  1520.         {
  1521.             fprintf(stderr, "Parse error: %s.\n", argv[i]);
  1522.             free(pred);
  1523.             return NULL;
  1524.         }
  1525.         break;
  1526.  
  1527.         case 2:
  1528.         /* Looking for an argument */
  1529.         if (isNumber(tok))
  1530.         {
  1531.             pred[predNum].argType = HE_NUMBER;
  1532.             pred[predNum].arg.i = atoi(tok);
  1533.         }
  1534.         else
  1535.         {
  1536.             pred[predNum].argType = HE_STRING;
  1537.             pred[predNum].arg.str = copyStr(tok);
  1538.         }
  1539.         state = 0;
  1540.         break;
  1541.  
  1542.         default:
  1543.         NOT_REACHED();
  1544.         break;
  1545.         }
  1546.     }
  1547.     }
  1548.     pred[++predNum].key = 0;
  1549.  
  1550.     return pred;
  1551. }
  1552.  
  1553. #ifdef PROTOTYPE
  1554. int satPred(DFdesc *desc, HE_PRED pred[])
  1555. #else
  1556. int satPred(desc, pred)
  1557.     DFdesc *desc;
  1558.     HE_PRED pred[];
  1559. #endif
  1560. {
  1561.     int i;
  1562.  
  1563.     if (!pred) return YES;
  1564.     for (i = 0; pred[i].key; i++)
  1565.     {
  1566.     switch(pred[i].key)
  1567.     {
  1568.     case HEK_ALL:
  1569.         return YES;        /* Always satisfied */
  1570.     case HEK_GROUP:
  1571.         if (!isGrp(desc->tag))
  1572.         return NO;
  1573.         break;
  1574.     case HEK_TAG:
  1575.         if (pred[i].argType != HE_NUMBER)
  1576.         {
  1577.         fprintf(stderr, "Argument to tag predicate not a number.");
  1578.         return NO;
  1579.         }
  1580.         if (!numCompare((int)desc->tag, pred[i].Comp, pred[i].arg.i))
  1581.         return NO;
  1582.         break;
  1583.     case HEK_REF:
  1584.         if (pred[i].argType != HE_NUMBER)
  1585.         {
  1586.         fprintf(stderr, "Argument to ref predicate not a number.");
  1587.         return NO;
  1588.         }
  1589.         if (!numCompare((int)desc->ref, pred[i].Comp, pred[i].arg.i))
  1590.         return NO;
  1591.         break;
  1592.     case HEK_SUCCEED:
  1593.         return (he_status == 0);
  1594.     case HEK_FAIL:
  1595.         return (he_status != 0);
  1596.     default:
  1597.         NOT_REACHED();
  1598.         break;
  1599.     }
  1600.     }
  1601.  
  1602.     return 1;
  1603. }
  1604.  
  1605. #ifdef PROTOTYPE
  1606. char *nextToken(char **p)
  1607. #else
  1608. char *nextToken(p)
  1609.     char **p;
  1610. #endif
  1611. {
  1612.     register char *s, *q;
  1613.     char *tok;
  1614.  
  1615.     if (!(**p)) return NULL;
  1616.  
  1617.     s = *p;
  1618.  
  1619.     if (isalnum(**p))
  1620.     while (isalnum(*s)) s++;
  1621.     else
  1622.     while (*s && !isalnum(*s)) s++;
  1623.  
  1624.     q = tok = (char *) malloc((s-(*p)) + 1);
  1625.     while (*p != s) *q++ = *(*p)++;
  1626.     *q = '\0';
  1627.  
  1628.     return tok;
  1629. }
  1630.     
  1631. #ifdef PROTOTYPE
  1632. int numCompare(int n1, int Comp, int n2)
  1633. #else
  1634. int numCompare(n1, Comp, n2)
  1635.     int n1, Comp, n2;
  1636. #endif
  1637. {
  1638.     switch(Comp)
  1639.     {
  1640.     case HEK_EQUAL:
  1641.     return (n1 == n2);
  1642.  
  1643.     case HEK_NEQUAL:
  1644.     return (n1 != n2);
  1645.  
  1646.     case HEK_GRT:
  1647.     return (n1 > n2);
  1648.  
  1649.     case HEK_GEQUAL:
  1650.     return (n1 >= n2);
  1651.  
  1652.     case HEK_LESST:
  1653.     return (n1 < n2);
  1654.  
  1655.     case HEK_LEQUAL:
  1656.     return (n1 <= n2);
  1657.  
  1658.     default:
  1659.     NOT_REACHED();
  1660.     break;
  1661.     }
  1662.     return NO;
  1663. }
  1664.  
  1665. /* end of cntrl.c */
  1666.